#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <cstdio>
#include <cstring>

// // 新线程
// void* run(void* args)
// {
// 	while(1)
// 	{
// 		std::cout << "new thread,pid:" << getpid() << std::endl;
// 		sleep(1);
// 	}
// 	return nullptr;
// }

// int main()
// {
// 	std::cout << "我是一个进程,pid:" << getpid() << std::endl;
// 	pthread_t tid;
// 	pthread_create(&tid,nullptr,run,(void*)"thread-1");

// 	// 主线程
// 	while(1)
// 	{
// 		std::cout << "main thread,pid:" << getpid() << std::endl;
// 		sleep(1);
// 	}

// 	return 0;
// }

// 线程创建

// class ThreadData
// {
// public:
// 	ThreadData(const std::string &name,int a,int b)
// 	:_name(name),_a(a),_b(b)
// 	{}
// 	void Excute() {_result = _a + _b;}
// 	int Result() {return _result;}
// 	std::string Name() {return _name;}
// 	~ThreadData() {}

// private:
// 	std::string _name;
// 	int _a;
// 	int _b;
// 	int _result;
// };

// int gval = 100; // 5.全局变量在线程内部是共享的

std::string toHex(pthread_t tid)
{
	// 4.进程内的函数，线程共享
	char buffer[64];
	snprintf(buffer, sizeof(buffer), "0x%lx", tid);
	return buffer;
}

// void* routine(void* args)
// {
// 	//std::string name = static_cast<const char*>(args);
// 	ThreadData* td = static_cast<ThreadData*>(args);
// 	while(1)
// 	{
// 		// 3.在不加保护的情况下，显示器文件就是共享资源
// 		//std::cout << "我是新线程，我的名字是: " << name << ",my tid is: " << toHex(pthread_self()) << std::endl;
// 		std::cout << "我是新线程，我的名字是: " << td->Name() << ",my tid is: " << toHex(pthread_self()) << std::endl;
// 		td->Excute();
// 		sleep(1);
// 		break;
// 	}
// 	//return (void*)10; // 线程退出方式1：线程入口函数return 表示线程退出

// 	// int* p = new int(10); // 方式2
// 	// return (void*)p;

// 	return td;   // 方式3
// }
// int main()
// {
// 	//1.新线程和main线程谁先运行，不确定
// 	//2.新线程创建出来，要对进程的时间片进行瓜分

// 	// pthread_t tid;
// 	//int n = pthread_create(&tid,nullptr,routine,(void*)"thread-1");
// 	// int n = pthread_create(&tid,nullptr,routine,(void*)"thread-1");
// 	// if(n != 0)
// 	// {
// 	// 	std::cout << "create thread error: " << strerror(n) << std::endl;
// 	// 	return 1;
// 	// }

// 	// 传参问题：传递参数，可以是变量，数字，对象
// 	pthread_t tid1;
// 	ThreadData *td = new ThreadData("thread-1",10,20);
// 	pthread_create(&tid1,nullptr,routine,td);

// 	// 线程创建之后，也是要被等待和回收的，理由：a.类似僵尸进程的问题 b.为了知道新线程的执行结果
// 	// 线程等待

// 	//int m = pthread_join(tid1,nullptr);
// 	//void* ret = nullptr;

// 	// void* ret = nullptr;
// 	// int m = pthread_join(tid1,&ret);

// 	ThreadData* rtd = nullptr;
// 	int m = pthread_join(tid1,(void**)&rtd);
// 	if(m != 0)
// 	{
// 		std::cerr << "join error:" << m << "," << strerror(m) << std::endl;
// 		return 1;
// 	}
// 	//std::cout << "join success! ret: " << *(int*)ret << std::endl;
// 	std::cout << "join success! ret: " << rtd->Result() << std::endl;

// 	// printf("new thread id: 0x%lx\n",tid);

// 	// while(1)
// 	// {
// 	// 	std::cout << "我是主线程" << std::endl;
// 	// 	sleep(1);
// 	// }

// 	return 0;
// }

// #define NUM 10

// class ThreadData
// {
// public:
// 	ThreadData() {}
// 	void Init(const std::string &name,int a,int b)
// 	{
// 		_name = name;
// 		_a = a;
// 		_b = b;
// 	}
// 	void Excute() {_result = _a + _b;}
// 	int Result() {return _result;}
// 	std::string Name() {return _name;}
// 	void SetId(pthread_t tid) {_tid = tid;}
// 	pthread_t Id() {return _tid;}
// 	int A() {return _a;}
// 	int B() {return _b;}
// 	~ThreadData() {}

// private:
// 	std::string _name;
// 	int _a;
// 	int _b;
// 	int _result;
// 	pthread_t _tid;
// };

// void* routine(void* args)
// {
// 	//std::string name = static_cast<const char*>(args);
// 	ThreadData* td = static_cast<ThreadData*>(args);
// 	while(1)
// 	{

// 		std::cout << "我是新线程，我的名字是: " << td->Name() << ",my tid is: " << toHex(pthread_self()) << std::endl;
// 		td->Excute();
// 		sleep(1);
// 		break;
// 	}
// 	return td;
// }

// int main()
// {
// 	ThreadData td[NUM];
// 	// 准备加工处理的数据
// 	for(int i = 0;i < NUM;i++)
// 	{
// 		char id[64];
// 		snprintf(id,sizeof(id),"thread-%d",i);
// 		td[i].Init(id,i*10,i*20);
// 	}

// 	// 创建多线程
// 	for(int i = 0;i < NUM;i++)
// 	{
// 		pthread_t id;
// 		pthread_create(&id,nullptr,routine,&td[i]);
// 		td[i].SetId(id);
// 	}

// 	// 等待多线程
// 	for(int i = 0;i < NUM;i++)
// 	{
// 		pthread_join(td[i].Id(),nullptr);
// 	}

// 	//汇总处理结果
// 	for(int i = 0;i < NUM;i++)
// 	{
// 		printf("td[%d]:%d+%d=%d[%ld]\n",i,td[i].A(),td[i].B(),td[i].Result(),td[i].Id());
// 	}
// }

// 每个线程都有自己独立的栈空间，它们共享进程的地址空间
// 每个线程的栈是单独分配的内存区域，物理地址上不重叠，但是通过指针刻意跨线程引用可以访问别的线程中栈的数据

// int* addr = nullptr;

// void* start1(void* args)
// {
// 	std::string name = static_cast<const char*>(args);
// 	int a = 100;
// 	addr = &a;
// 	while(1)
// 	{
// 		std::cout << name << "local val a: " << a << std::endl;
// 		sleep(1);
// 	}
// }
// void* start2(void* args)
// {
// 	std::string name = static_cast<const char*>(args);
// 	while(1)
// 	{
// 		if(addr != nullptr)
// 			std::cout << name << "mod val a: " << (*addr)++ << std::endl;
// 		sleep(1);
// 	}
// }

// int main()
// {
// 	pthread_t tid1,tid2;
// 	pthread_create(&tid1,nullptr,start1,(void*)"thread-1");
// 	pthread_create(&tid1,nullptr,start2,(void*)"thread-2");

// 	pthread_join(tid1,nullptr);
// 	pthread_join(tid2,nullptr);

// 	return 0;
// }







// 进程退出

// void *start(void *args)
// {
// 	std::string name = static_cast<const char *>(args);
// 	while (1)
// 	{
// 		std::cout << "I am a new thread" << std::endl;
// 		sleep(1);
// 	}
// 	// return 0;  //1.新线程return表示线程退出
// 	// exit(0);   //任何地方exit，表示进程结束

// 	pthread_exit((void*)10);  //2.线程退出与return等价
// }
// int main()
// {
// 	pthread_t tid;
// 	pthread_create(&tid, nullptr, start, (void*)"thread-1");

// 	sleep(5);

// 	pthread_cancel(tid); // 线程取消,也必须得进行join,退出码为-1   PTHREAD_CANCELED
// 	std::cout << "thread cancel" << std::endl;

// 	sleep(5);

// 	void* ret = nullptr;
// 	pthread_join(tid,&ret);

// 	std::cout << "new thread exit code: " << (long long int)ret << std::endl;
// 	return 0;
// }





// 线程分离
// 线程有两种被等待状态   
// 1.joined:线程需要被join(默认)   2.detach:线程分离(主线程不需要等待新线程)


// void *start(void *args)
// {
// 	//pthread_detach(pthread_self());

// 	std::string name = static_cast<const char *>(args);
// 	while (1)
// 	{
// 		std::cout << "I am a new thread" << std::endl;
// 		sleep(1);
// 	}
// }
// int main()
// {
// 	pthread_t tid;
// 	pthread_create(&tid, nullptr, start, (void*)"thread-1");

// 	// pthread_detach(tid); //线程被分离了就不能被join了

// 	sleep(5);

// 	void* ret = nullptr;
// 	int n = pthread_join(tid,&ret);

// 	std::cout << "new thread exit code: " << (long long int)ret << ",n: " << n << std::endl;
// 	return 0;
// }






// 线程ID 
// pthread_self()可以拿到当前线程的id
// 但是这个结果实际上就是一个地址值，所以所谓的线程id实际上就是一个地址值而并不是LWP值


// void *start(void *args)
// {
// 	std::string name = static_cast<const char*>(args);

// 	while(1)
// 	{
// 		std::cout << "I am a new thread,name " << name << ",thread id: " << toHex(pthread_self()) << std::endl; 
// 		sleep(1);
// 	}
// 	return nullptr;
// }
// int main()
// {
// 	pthread_t tid;
// 	pthread_create(&tid, nullptr, start, (void*)"thread-1");
// 	std::cout << "I am main thread,id: " << toHex(pthread_self()) << "new thread: " << toHex(tid) << std::endl;

// 	pthread_join(tid,nullptr);
// 	return 0;
// }






// 线程的局部存储


//int shared_value = 100;
__thread int shared_value = 100; // 编译性关键字，__thread只能修饰内置类型


void *start(void *args)
{
	std::string name = static_cast<const char*>(args);

	while(1)
	{
		printf("new thread,shared_value:%d,&share_value:%p\n",shared_value,&shared_value);
		sleep(1);
	}
	return nullptr;
}
int main()
{
	pthread_t tid;
	pthread_create(&tid, nullptr, start, (void*)"thread-1");
    
	while(1)
	{
		printf("main thread,shared_value:%d,&share_value:%p\n",shared_value,&shared_value);
        shared_value += 10;
		sleep(1);
	}
	pthread_join(tid,nullptr);
	return 0;
}